﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace game
{
    public class Layer : IEnumerable<GameObject>
    {
        public List<GameObject> GameObjects { get { return gameObjects; } }
        
        public int Index { get { return index; } }
        public float Height { get; set; }

        private Queue<GameObject> objectsToAdd;
        private Queue<GameObject> objectsToRemove;

        private List<GameObject> gameObjects = null;
        private int index = -1;

        private Scene scene;

        public Layer(Scene scene, int index, float height)
        {
            this.scene = scene;
            this.index = index;
            Height = height;

            gameObjects = new List<GameObject>(); // new LinkedList<GameObject>();
            objectsToAdd = new Queue<GameObject>();
            objectsToRemove = new Queue<GameObject>();
        }

        public void Update(GameTime gameTime)
        {
            while (objectsToRemove.Count > 0)
            {
                gameObjects.Remove(objectsToRemove.Dequeue());
            }
            while (objectsToAdd.Count > 0)
            {
                gameObjects.Add(objectsToAdd.Dequeue());
            }
        }

        public void CheckCollisions()
        {
            GameObject obj1, obj2;
            for (int i = 0; i < gameObjects.Count; i++)
            {
                obj1 = gameObjects[i];
                if (!obj1.IsAlive)
                    continue;

                BoundingSphere obj1BSphere = obj1.GetBSphereTransformed();

                for (int j = i+1; j < gameObjects.Count; j++)
                {
                    if (!obj1.IsAlive)
                        break;

                    obj2 = gameObjects[j];
                    if (!obj2.IsAlive)
                        continue;

                    BoundingSphere obj2BSphere = obj2.GetBSphereTransformed();

                    if (obj1BSphere.Intersects(obj2BSphere) &&
                        obj1.Collide(obj2) && obj2.Collide(obj1))
                    {
                        obj1.Collision(obj2);
                        obj2.Collision(obj1);
                    }
                }
            }
        }

        public bool CheckCollisions(GameObject gameObj)
        {
            if (!gameObjects.Contains(gameObj) || !gameObj.IsAlive)
            {
                return false;
            }

            bool result = false;
            BoundingSphere srcBSphere = gameObj.GetBSphereTransformed();
            foreach (GameObject obj in gameObjects)
            {
                BoundingSphere checkBSphere = obj.GetBSphereTransformed();
                if (gameObj != obj && obj.IsAlive && srcBSphere.Intersects(checkBSphere)
                    && gameObj.Collide(obj) && obj.Collide(gameObj))
                {
                    result = true;
                    gameObj.Collision(obj);
                    obj.Collision(gameObj);
                }
            }
            return result;
        }

        public void RemoveObject(GameObject obj)
        {
            objectsToRemove.Enqueue(obj);
        }

        public void AddObject(GameObject obj)
        {
            objectsToAdd.Enqueue(obj);
        }

        public Ship GetClosestEnemy(Ship ship)
        {
            float distSquare = float.MaxValue;
            Ship closestEnemy = null;

            float newDist = 0.0f;

            foreach (GameObject obj in gameObjects)
            {
                if (obj is Ship && ((Ship)obj).Army.ID != ship.Army.ID)
                {
                    newDist = (obj.Position.X - ship.Position.X) * (obj.Position.X - ship.Position.X)
                            + (obj.Position.Z - ship.Position.Z) * (obj.Position.Z - ship.Position.Z);
                    if (newDist < distSquare)
                    {
                        distSquare = newDist;
                        closestEnemy = (Ship)obj;
                    }
                }
            }
            return closestEnemy;
        }


        public bool AreAnyEnemies(Ship ship)
        {
            foreach (GameObject obj in gameObjects)
            {
                if (obj is Ship && ((Ship)obj).Army.ID != ship.Army.ID)
                    return true;
            }
            return false;
        }


        #region IEnumerable<GameObject> Members

        public IEnumerator<GameObject> GetEnumerator()
        {
            foreach (GameObject obj in gameObjects)
            {
                if(!obj.IsMultiLayer)
                    yield return obj;
            }
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
